/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkRtspSubSession.h"
#include "MkRtspUtil.h"
#include "MkRtp/MkRtpUdpServer.h"
#include "MkUtil/MkUtil.h"
#include "MkUtil/MkLog.h"

CMkRtspSubSession::CMkRtspSubSession(const MkString& RtpHost, const MkVideoAudioSetCallback& SetCb)
    : m_RtpRemoteHost(RtpHost)
    , m_TimeOut(0)
    , m_RtpUdpServer(nullptr)
    , m_VideoAudioSetCb(SetCb)
    , m_Codec(MkCodecUnknown)
    , m_Ssrc(MaxUint32)
    , m_SeqNumber(0)
{
}

Uint32 CMkRtspSubSession::SetSdpMedia(const CMkSdpMedia& SdpMedia)
{
    m_SdpMedia = SdpMedia;
    MkString MediaType = m_SdpMedia.GetMediaType();
    m_Uri = m_SdpMedia.GetControlUri();
    m_PlayStartTime = m_SdpMedia.GetPlayStartTime();
    m_PlayEndTime = m_SdpMedia.GetPlayEndTime();
    m_AbsStartTime = m_SdpMedia.GetAbsStartTime();
    m_AbsEndTime = m_SdpMedia.GetAbsStartTime();
    m_Mikey = m_SdpMedia.GetMikey();
    const MkMap<Uint32, CMkSdpFmt> MapFmt = m_SdpMedia.GetFmts();
    if ("video" == MediaType) {
        CMkVideoParam VideoParam;
        VideoParam.SetBitRate(m_SdpMedia.GetBandWidth());
        VideoParam.SetFrameRate(m_SdpMedia.GetVideoFrameRate());
        VideoParam.SetHeight(m_SdpMedia.GetVideoHeight());
        VideoParam.SetWidth(m_SdpMedia.GetVideoWidth());
        if (!MapFmt.empty()) {
            VideoParam.SetCodec(CMkMediaUtil::GetInstance().GetCodec(MapFmt.begin()->second.GetEncodingName()));
            VideoParam.SetVps(MapFmt.begin()->second.GetVps());
            VideoParam.SetPps(MapFmt.begin()->second.GetPps());
            VideoParam.SetSps(MapFmt.begin()->second.GetSps());
            m_PayloadType = MapFmt.begin()->second.GetPayload();
            //m_H264ProfileLevelId = MapFmt.begin()->second.GetProfileLevelId();
            //m_H264PacketMode = MapFmt.begin()->second.GetH264PacketMode();
            m_Codec = VideoParam.GetCodec();
            if (!VideoParam.GetFrameRate()
                || VideoParam.GetWidth()
                || VideoParam.GetHeight()) {
                Uint32 Width = 0;
                Uint32 Height = 0;
                Uint32 FrameRate = 25;
                if (MkCodecH264 == VideoParam.GetCodec()) {
                    CMkMediaUtil::H264SpsParse((const Uint8*)VideoParam.GetSps().c_str(), VideoParam.GetSps().size(), Width, Height, FrameRate);
                } else if (MkCodecH265 == VideoParam.GetCodec()) {
                    CMkMediaUtil::H265SpsParse((const Uint8*)VideoParam.GetSps().c_str(), VideoParam.GetSps().size(), Width, Height);
                }
                VideoParam.SetWidth(Width);
                VideoParam.SetHeight(Height);
                VideoParam.SetFrameRate(FrameRate);
            }
        }
        if (m_VideoAudioSetCb) {
            m_VideoAudioSetCb(VideoParam, CMkAudioParam());
        }
    } else if ("audio" == MediaType) { //audio
        CMkAudioParam AudioParam;
        AudioParam.SetBitRate(m_SdpMedia.GetBandWidth());
        if (!MapFmt.empty()) {
            AudioParam.SetCodec(CMkMediaUtil::GetInstance().GetCodec(MapFmt.begin()->second.GetEncodingName()));
            AudioParam.SetSampletRate(CMkMediaUtil::AudioSampleRateToIndex(MapFmt.begin()->second.GetClockRate()));
            AudioParam.SetChannel(MapFmt.begin()->second.GetEncodingParams());
            m_Codec = AudioParam.GetCodec();
            if (m_VideoAudioSetCb) {
                m_VideoAudioSetCb(CMkVideoParam(), AudioParam);
            }
        }
    } else {
        MkWarningLog("recv not audio video media type\n");
    }
    return NoneError;
}

Uint16 CMkRtspSubSession::GetRtpLocalUdpPort()
{
    if (m_RtpUdpServer) {
        return m_RtpUdpServer->GetRtpPort();
    }
    return 0;
}

Uint32 CMkRtspSubSession::SendRtpPacket(const CMkRtpPacket& RtpPacket)
{
    if (m_RtpUdpServer) {
        m_RtpUdpServer->SendRtpPacket(RtpPacket, m_RtpRemoteHost, m_RtpRemotePort);
    }
    return NoneError;
}

CMkRtspSubSession::~CMkRtspSubSession()
{
    if (m_RtpUdpServer) {
        m_RtpUdpServer->DeleteRemoter(m_Ssrc);
    }
}

